/**
 * 对公众平台发送给公众账号的消息加解密示例代码.
 *
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */

// ------------------------------------------------------------------------

package cn.izeno.wx.aes

import org.xml.sax.InputSource
import java.io.StringReader
import javax.xml.parsers.DocumentBuilderFactory

/**
 * XMLParse class
 *
 * 提供提取消息格式中的密文及生成回复消息格式的接口.
 */
internal object XMLParse {

  /**
   * 提取出xml数据包中的加密消息
   * @param xmltext 待提取的xml字符串
   * @return 提取出的加密消息字符串
   * @throws AesException
   */
  @Throws(AesException::class)
  fun extract(xmltext: String): Array<Any> {
    try {
      val dbf = DocumentBuilderFactory.newInstance()
      dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
      dbf.setFeature("http://xml.org/sax/features/external-general-entities", false)
      dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false)
      dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
      dbf.isXIncludeAware = false
      dbf.isExpandEntityReferences = false
      val db = dbf.newDocumentBuilder()
      val sr = StringReader(xmltext)
      val `is` = InputSource(sr)
      val document = db.parse(`is`)

      val root = document.documentElement
      val nodelist1 = root.getElementsByTagName("Encrypt")
      val nodelist2 = root.getElementsByTagName("ToUserName")
      return arrayOf(0, nodelist1.item(0).textContent, nodelist2.item(0).textContent)
    } catch (e: Exception) {
      e.printStackTrace()
      throw AesException(AesException.ParseXmlError)
    }

  }

  /**
   * 生成xml消息
   * @param encrypt 加密后的消息密文
   * @param signature 安全签名
   * @param timestamp 时间戳
   * @param nonce 随机字符串
   * @return 生成的xml字符串
   */
  fun generate(encrypt: String, signature: String, timestamp: String, nonce: String): String {

    val format = ("<xml>\n" + "<Encrypt><![CDATA[%1\$s]]></Encrypt>\n"
        + "<MsgSignature><![CDATA[%2\$s]]></MsgSignature>\n"
        + "<TimeStamp>%3\$s</TimeStamp>\n" + "<Nonce><![CDATA[%4\$s]]></Nonce>\n" + "</xml>")
    return String.format(format, encrypt, signature, timestamp, nonce)

  }
}
